package com.cy.aircompressor.main.view.chart;

import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.FrameLayout;
import android.widget.LinearLayout;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.cy.aircompressor.databinding.ItemLineChartTrendBinding;
import com.cy.aircompressor.entity.linechart.LineChartEntry;
import com.cy.aircompressor.entity.linechart.LineChartItemEntry;
import com.cy.aircompressor.entity.linechart.LineLegend;
import com.cy.aircompressor.entity.linechart.LineNewData;
import com.cy.aircompressor.entity.sensor.SensorAgg;
import com.cy.aircompressor.entity.sensor.SensorItemData;
import com.cy.aircompressor.entity.sensor.SensorLatestData;
import com.cy.aircompressor.entity.sensor.SensorStatisticsData;
import com.cy.aircompressor.main.home.dialog.FullScreenDialog;
import com.cy.aircompressor.main.home.fragment.v2.LineChartHelper;
import com.cy.aircompressor.main.ui.onlinemonitor.utils.LineChartUtil;
import com.drug.lib.util.DensityUtil;
import com.github.mikephil.charting.data.Entry;
import com.jakewharton.rxbinding2.view.RxView;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class LineChartView extends FrameLayout {
    private Context mContext;
    private ItemLineChartTrendBinding mBinding;
    private LineChartItemEntry itemEntry;
    private List<LatestDataView> latestDataViews;
    private List<LegendView> legendViews;

    public LineChartView(@NonNull Context context) {
        this(context, null);
    }

    public LineChartView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LineChartView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public LineChartView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        this.mContext = context;
        initView();
    }

    private void initView() {
        mBinding = ItemLineChartTrendBinding.inflate(LayoutInflater.from(getContext()));
        addView(mBinding.getRoot());
        latestDataViews = new ArrayList<>();
        legendViews = new ArrayList<>();
    }


    /**
     * 初始化Item
     *
     * @param itemEntry
     */
    public void init(LineChartItemEntry itemEntry) {
        this.itemEntry = itemEntry;
        initHeadView();
        initNewDataItem();
        initLineLegend();
        LineChartUtil.initLineChart(mBinding.lineChart, false);
        notifyDataSetChanged();
    }

    /**
     * 初始化头部view
     */
    private void initHeadView() {
        mBinding.titleName.setText(itemEntry.getTitleName());
        mBinding.textUnit.setText(itemEntry.getUnit());
        mBinding.switchLine.setVisibility(itemEntry.isVibration() ? VISIBLE : GONE);
        if (itemEntry.isVibration())
            mBinding.switchLine.setText(itemEntry.isSpeed() ? "切换speed曲线" : "切换rms曲线");
        RxView.clicks(mBinding.switchLine)
                .throttleFirst(500, TimeUnit.MILLISECONDS)
                .subscribe(o -> {
                    itemEntry.setSpeed(!itemEntry.isSpeed());
                    mBinding.switchLine.setText(itemEntry.isSpeed() ? "切换speed曲线" : "切换rms曲线");
                    notifyDataSetChanged();
                });
        RxView.clicks(mBinding.fullScreen)
                .throttleFirst(500, TimeUnit.MILLISECONDS)
                .subscribe(o -> {
                    FullScreenDialog.showDialogFragment(LineChartHelper.get().fragmentManager, "linechart", itemEntry);
//                    if (lineChartClickCallBack != null) lineChartClickCallBack.fullScreen();
                });
    }

    /**
     * 初始化最新数据
     */
    public void initNewDataItem() {
        List<LineNewData> lineNewDatas = itemEntry.getLineNewDatas();
        if (lineNewDatas == null) return;
        if (lineNewDatas.size() == 0) return;
        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        layoutParams.leftMargin = DensityUtil.dip2px(8);
        lineNewDatas.forEach(new Consumer<LineNewData>() {
            @Override
            public void accept(LineNewData lineNewData) {
                LatestDataView latestDataView = new LatestDataView(mContext);
                latestDataView.initLineNewData(lineNewData);
                latestDataView.setLayoutParams(layoutParams);
                mBinding.newDataView.addView(latestDataView);
                latestDataViews.add(latestDataView);
            }
        });

    }

    /**
     * 初始化图例
     */
    public void initLineLegend() {
        List<LineLegend> lineLegends = itemEntry.getLineLegends();
        if (lineLegends == null) return;
        if (lineLegends.size() == 0) return;
        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        layoutParams.topMargin = DensityUtil.dip2px(3);
        lineLegends.forEach(new Consumer<LineLegend>() {
            @Override
            public void accept(LineLegend lineNewData) {
                LegendView legendView = new LegendView(mContext);
                legendView.setLegend(lineNewData);
                legendView.setLayoutParams(layoutParams);
                mBinding.legendView.addView(legendView);
                legendViews.add(legendView);
            }
        });

    }

    public void notifyDataSetChanged() {
        refreshAllLatestData();
        refreshLineChart();
    }

    /**
     * ======================================刷新最新数据，开始==============================================================
     * 刷新最新数据
     */
    private void refreshAllLatestData() {
        latestDataViews.forEach(new Consumer<LatestDataView>() {
            @Override
            public void accept(LatestDataView latestDataView) {
                SensorLatestData sensorLatestData = itemEntry.getSensorLatestData();
                if (sensorLatestData == null) {
                    latestDataView.setDefault();
                    return;
                }

                LineNewData lineNewData = latestDataView.getLineNewData();
                SensorItemData sensorItemData = getSensorItemData(lineNewData.getPartCode(), lineNewData.getPointCode(), sensorLatestData.getDataList());
                if (sensorItemData == null) {
                    latestDataView.setDefault();
                    return;
                }

                String value = getValue(lineNewData, sensorItemData);
                latestDataView.setValue(value);
            }
        });
    }


    private String getValue(LineNewData lineNewData, SensorItemData sensorItemData) {
        String value = "";
        if (TextUtils.equals(lineNewData.getPartCode(), "body") && lineNewData.getPointCode().contains("vibration")) {
            switch (lineNewData.getName()) {
                case "x轴":
                    value = String.valueOf(itemEntry.isSpeed() ? sensorItemData.getXspeed() : sensorItemData.getXrms());
                    break;
                case "y轴":
                    value = String.valueOf(itemEntry.isSpeed() ? sensorItemData.getYspeed() : sensorItemData.getYrms());
                    break;
                case "z轴":
                    value = String.valueOf(itemEntry.isSpeed() ? sensorItemData.getZspeed() : sensorItemData.getZrms());
                    break;
            }
        } else {
            value = sensorItemData.getV();
        }
        return value;
    }

    private SensorItemData getSensorItemData(String partCode, String pointCode, List<SensorItemData> dataList) {
        if (dataList == null)
            return null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
            List<SensorItemData> sensorItemDataList = dataList.stream()
                    .filter(new Predicate<SensorItemData>() {
                        @Override
                        public boolean test(SensorItemData sensorItemData) {
                            return TextUtils.equals(sensorItemData.getCompressorPartCode(), partCode) &&
                                    TextUtils.equals(sensorItemData.getCompressorPointCode(), pointCode);
                        }
                    }).collect(Collectors.toList());
            if (sensorItemDataList != null && sensorItemDataList.size() > 0) {
                return sensorItemDataList.get(0);
            }
        }
        return null;

    }

    /**
     * ===================================================刷新最新数据，结束========================================================
     */


    /**
     * ===================================================刷新传感数据器统计图，开始========================================================
     * 刷新曲线图
     */
    private void refreshLineChart() {
        List<SensorAgg> sensorAggs = itemEntry.getSensorAggs();
        if (sensorAggs == null || (sensorAggs != null && sensorAggs.size() == 0)) {
            LineChartUtil.addEmptyLine(mBinding.lineChart);
            return;
        }
        if (itemEntry.isVibration()) {
            rightStatisticsData(sensorAggs.get(0));
        } else {
            leftStatisticsData(sensorAggs);
        }
    }

    /**
     * 加载数据到左侧UI
     *
     * @param sensorAggs
     */
    private void leftStatisticsData(List<SensorAgg> sensorAggs) {
        List<LineChartEntry> lineChartEntries = new ArrayList<>();
        sensorAggs.forEach(new Consumer<SensorAgg>() {
            @Override
            public void accept(SensorAgg sensorAgg) {
                List<SensorStatisticsData> statisticsDataList = sensorAgg.getSensorStatisticsData();
                if (statisticsDataList != null && statisticsDataList.size() != 0) {
                    LineChartEntry lineChartEntry = new LineChartEntry();
                    List<Entry> entries = getChartEntry(statisticsDataList);
                    lineChartEntry.setEntrys(entries);
                    lineChartEntry.setColor(getColor(sensorAgg));
                    lineChartEntries.add(lineChartEntry);
                }
            }
        });

        if (lineChartEntries == null || (lineChartEntries != null && lineChartEntries.size() == 0)) {
            LineChartUtil.addEmptyLine(mBinding.lineChart);
        } else {
            LineChartUtil.addAndUpdateLine(mBinding.lineChart, lineChartEntries);
        }
        LineChartUtil.checkLineChart(mBinding.lineChart);
    }

    private List<Entry> getChartEntry(List<SensorStatisticsData> statisticsData) {
        List<Entry> entries = new ArrayList<>();
        if (statisticsData != null && statisticsData.size() != 0) {
            for (int i = 0; i < statisticsData.size(); i++) {
                SensorStatisticsData sensorStatisticsData = statisticsData.get(i);
                long time = getDate(sensorStatisticsData.getRt());
                Entry entry = new Entry(i, (float) sensorStatisticsData.getV(), time);
                entries.add(entry);
            }
        }
        return entries;
    }

    /**
     * 加载数据到右侧UI
     *
     * @param sensorAgg
     */
    private void rightStatisticsData(SensorAgg sensorAgg) {
        List<SensorStatisticsData> sensorStatisticsData = sensorAgg.getSensorStatisticsData();
        if (sensorStatisticsData == null || (sensorStatisticsData != null && sensorStatisticsData.size() == 0)) {
            LineChartUtil.addEmptyLine(mBinding.lineChart);
            return;
        }

        Map<String, List<Entry>> listMap = getLineChartEntryMaps(sensorStatisticsData);
        List<LineChartEntry> lineChartEntries = new ArrayList<>();
        listMap.forEach(new BiConsumer<String, List<Entry>>() {
            @Override
            public void accept(String s, List<Entry> entries) {
                LineChartEntry lineChartEntry = new LineChartEntry();
                lineChartEntry.setColor(LineChartHelper.get().getColor(s));
                lineChartEntry.setEntrys(entries);
                lineChartEntries.add(lineChartEntry);
            }
        });
        LineChartUtil.addAndUpdateLine(mBinding.lineChart, lineChartEntries);

    }

    private Map<String, List<Entry>> getLineChartEntryMaps(List<SensorStatisticsData> sensorStatisticsData) {
        List<Entry> entrieX = new ArrayList<>();
        List<Entry> entrieY = new ArrayList<>();
        List<Entry> entrieZ = new ArrayList<>();
        for (int i = 0; i < sensorStatisticsData.size(); i++) {
            SensorStatisticsData statisticsData = sensorStatisticsData.get(i);
            long time = getDate(statisticsData.getRt());
            Entry entry = new Entry(i, itemEntry.isSpeed() ? statisticsData.getXspeed() : statisticsData.getXrms(), time);
            entrieX.add(entry);

            entry = new Entry(i, itemEntry.isSpeed() ? statisticsData.getYspeed() : statisticsData.getYrms(), time);
            entrieY.add(entry);

            entry = new Entry(i, itemEntry.isSpeed() ? statisticsData.getZspeed() : statisticsData.getZrms(), time);
            entrieZ.add(entry);
        }
        Map<String, List<Entry>> entryMap = new HashMap<>();
        entryMap.put("x", entrieX);
        entryMap.put("y", entrieY);
        entryMap.put("z", entrieZ);
        return entryMap;
    }

    /**
     * ===================================================刷新传感数据器统计图，结束========================================================
     */


    private long getDate(String rt) {
        Date date = null;
        try {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            date = format.parse(rt);
            return date.getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }

        return 0;
    }

    private String getColor(SensorAgg sensorAgg) {
        String code;
        if (TextUtils.equals(sensorAgg.getSensor().getCompressorPointCode(), "pressure_oil"))
            code = sensorAgg.getSensor().getCompressorPointCode();
        else if (TextUtils.equals(sensorAgg.getSensor().getCompressorPointCode(), "pressure_water"))
            code = sensorAgg.getSensor().getCompressorPointCode();
        else
            code = sensorAgg.getSensor().getCompressorPartCode();
        return LineChartHelper.get().getColor(code);
    }


    public LineChartItemEntry getItemEntry() {
        return itemEntry;
    }


    LineChartClickCallBack lineChartClickCallBack;

    public void setLineChartClickCallBack(LineChartClickCallBack lineChartClickCallBack) {
        this.lineChartClickCallBack = lineChartClickCallBack;
    }

    public interface LineChartClickCallBack {
        void fullScreen();
    }
}
